#include "TcpServer.h"

TcpServer::TcpServer(short port, int threadCount) : 
    m_acceptor(m_ioContext, tcp::endpoint(tcp::v4(), port)), 
    m_threadCount(threadCount)
{
}

TcpServer::~TcpServer() 
{
    Stop();
}

void TcpServer::Start()
{
    for (int i = 0; i < m_threadCount; i++)
    {
        m_threads.create_thread(std::bind(&TcpServer::RunIoContext, shared_from_this()));
    }

    StartAccept();      // 启动监听。
    
    std::cout << "Server thread count:" << m_threads.size() << std::endl;
}

void TcpServer::Stop()
{
    m_beStop = true;
    m_ioContext.stop();
    std::cout << "Server stopped." << std::endl;
}

bool TcpServer::AddSession(std::shared_ptr<Session> session)
{
    std::lock_guard<std::mutex> lock(m_sessionMapLock);
    auto it = m_sessionMap.find(session->GetName());
    if (it!= m_sessionMap.end())
    {
        return false;
    }

    auto ret = m_sessionMap.insert({session->GetName(), session});
    return ret.second;
}

void TcpServer::DeleteSession(const std::string& name)
{
    std::lock_guard<std::mutex> lock(m_sessionMapLock);
    auto it = m_sessionMap.find(name);
    if (it!= m_sessionMap.end())
    {
        it->second->Stop();
        m_sessionMap.erase(it);
        std::cout << "server erase Session name:" << name << std::endl;
    }
}

void TcpServer::DeleteAllSession()
{
    std::lock_guard<std::mutex> lock(m_sessionMapLock);
    for (auto it = m_sessionMap.begin(); it!= m_sessionMap.end(); ++it)
    {
        it->second->Stop();
    }
    m_sessionMap.clear();
    std::cout << "server clear all Session" << std::endl;
}

std::shared_ptr<Session> TcpServer::GetSession(const std::string& name)
{
    std::lock_guard<std::mutex> lock(m_sessionMapLock);
    auto it = m_sessionMap.find(name);
    if (it!= m_sessionMap.end())
    {
        return it->second;
    }
    return nullptr;
}

void TcpServer::SendTo(const std::string& name, const std::string& message)
{
    std::lock_guard<std::mutex> lock(m_sessionMapLock);
    auto it = m_sessionMap.find(name);
    if (it!= m_sessionMap.end())
    {
        it->second->Send(message);
    }
}

void TcpServer::SendToAll(const std::string& message)
{
    std::lock_guard<std::mutex> lock(m_sessionMapLock);
    for (auto it = m_sessionMap.begin(); it!= m_sessionMap.end(); ++it)
    {
        it->second->Send(message);
    }
}


void TcpServer::OnSessionClose(const std::string& name)
{
    DeleteSession(name);       
}

void TcpServer::StartAccept() 
{
    std::cout << "StartAccept...." << std::endl;

    TcpSocketPtr tmpsocket = std::make_shared<tcp::socket>(m_ioContext);
    m_acceptor.async_accept(*tmpsocket, 
        std::bind(&TcpServer::HandleAccept, shared_from_this(), tmpsocket, std::placeholders::_1));       
}


void TcpServer::HandleAccept(TcpSocketPtr socket, const boost::system::error_code &ec)
{
    if (!ec)
    {
        std::cout << "tcpserver accept client." << std::endl;
        std::shared_ptr<Session> sessionPtr = m_createSessionObjFunc(socket);
        if (sessionPtr != nullptr)
        {
            sessionPtr->SetCloseCallback(std::bind(&TcpServer::OnSessionClose, this, std::placeholders::_1));
            AddSession(sessionPtr);                         // 加入session列表，方便统一管理
            sessionPtr->Start();                            // 启动session，接收数据
        }
        else
        {
            std::cout << "tcpserver Create SessionObj failed." << std::endl;
        }
    }
    else
    {
        std::cout << "tcpserver accept client failed." << std::endl;
    }

    StartAccept();  // 继续监听客户端连接请求
}

void TcpServer::RunIoContext()
{
    m_ioContext.run();
    std::cout << "TcpServer out ..." << std::endl;
}